/*
 * Galaxium Messenger
 * Copyright (C) 2007 Ben Motmans <ben.motmans@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.IO;
using System.Collections.Generic;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Client;

namespace Galaxium.Protocol.Msn
{
	public sealed class MsnFileTransfer : AbstractFileTransfer
	{
		private P2PFileTransfer _transfer;
		
		public P2PFileTransfer P2PTransfer
		{
			get { return _transfer; }
		}
		
		public MsnFileTransfer (ISession session, IContact contact, string fileName)
			: base (session, contact, false, fileName)
		{
			ThrowUtility.ThrowIfFalse ("File doesn't exist", File.Exists (fileName));
			
			_transfer = new P2PFileTransfer (contact as MsnContact, fileName);
			
			_transfer.Began += TransferStarted;
			_transfer.Complete += TransferFinished;
			_transfer.LocallyCancelled += TransferLocallyAborted;
			_transfer.RemotelyCancelled += TransferRemotelyAborted;
			_transfer.Progressed += TransferProgressed;
			
			Stream = _transfer.DataStream;
			TotalBytes = (long)_transfer.Context.FileSize;
			TransferedBytes = 0;
		}
		
		internal MsnFileTransfer (ISession session, IContact contact, P2PFileTransfer transfer)
			: base (session, contact, true, transfer.Context.Filename)
		{
			_transfer = transfer;
			
			_transfer.Began += TransferStarted;
			_transfer.Complete += TransferFinished;
			_transfer.LocallyCancelled += TransferLocallyAborted;
			_transfer.RemotelyCancelled += TransferRemotelyAborted;
			_transfer.Progressed += TransferProgressed;
			
			if (_transfer.Context.Preview.Length > 0)
				base._preview = _transfer.Context.Preview;
			
			Stream = _transfer.DataStream;
			TotalBytes = (long)_transfer.Context.FileSize;
			TransferedBytes = 0;
		}
		
		public override void Accept ()
		{
			if (Incoming)
				_transfer.Accept ();
		}
		
		public override void Decline ()
		{
			if (Incoming)
				_transfer.Decline ();
		}
		
		public override void Abort ()
		{
			if (_transfer != null)
				_transfer.Cancel ();
		}
		
		public override void Rename (string filename)
		{
			if (Stream == null)
				_fileName = filename;
			else
			{
				// We somehow need to check if we are doing an incoming, and if it hasnt started yet.
				if (Incoming)
				{
					if (TransferedBytes == 0)
					{
						_transfer.DataStream.Close();
						
						if (File.Exists (Path.Combine(FileTransferUtility.DestinationFolder, _fileName)))
							File.Delete (Path.Combine(FileTransferUtility.DestinationFolder, _fileName));
						
						_fileName = filename;
						_transfer.DataStream = File.Open(Path.Combine (FileTransferUtility.DestinationFolder, _fileName), FileMode.Create);
						Stream = _transfer.DataStream;
					}
				}
				else
					Log.Warn ("Cannot rename outgoing file as the stream is already opened with the existing filename!");
			}
		}
		
		private void TransferStarted (object sender, EventArgs args)
		{
			_startTime = DateTime.Now;
			
			OnTransferStart (new FileTransferEventArgs (this));
		}
		
		private void TransferFinished (object sender, EventArgs args)
		{
			OnTransferFinish (new FileTransferEventArgs (this));
		}
		
		private void TransferLocallyAborted (object sender, EventArgs args)
		{
			OnTransferLocalAbort (new FileTransferEventArgs (this));
		}
		
		private void TransferRemotelyAborted (object sender, EventArgs args)
		{
			OnTransferRemoteAbort (new FileTransferEventArgs (this));
		}
		
		private void TransferProgressed (object sender, EventArgs args)
		{
			TransferedBytes = (long)_transfer.Transferred;
			
			OnTransferProgress (new FileTransferEventArgs (this));
		}
	}
}